<?php

namespace app\model\v1;

use app\BaseModel;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\HttpException;
use think\exception\ValidateException;
use think\facade\Request;

// 管理员
class Manager extends BaseModel
{
    /**
     * 一对一
     * 基于管理员表的 role_id 关联角色表的 id
     * @return \think\model\relation\HasOne
     */
    public function role(): \think\model\relation\HasOne
    {
        return $this->hasOne(Role::class, 'id', 'role_id');
    }

    /**
     * 一对一
     * 基于管理员表的 image_id 关联图片表的 id
     * @return \think\model\relation\HasOne
     */
    public function image(): \think\model\relation\HasOne
    {
        return $this->hasOne(Image::class, 'id', 'image_id');
    }

    /**
     * 密码获取器 密码返回空
     * @param $value
     * @return string
     */
    public function getPasswordAttr($value): string
    {
        return '';
    }

    /**
     * 账号密码查询用户信息
     * @param string $account
     * @param string $password
     * @return array|\think\Model
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function infoByAccountPwd(string $account, string $password) {
        $managerInfo = $this->where([
            'account'   => $account,
            'password'  =>  md5($password),
        ])->with('role')->find();
        if (!$managerInfo) {
            throw new ValidateException('账号或密码错误');
        }
        if ($managerInfo->getAttr('status') == 1) {
            throw new ValidateException('您的帐户已被冻结，请联系管理员');
        }
        // 更新登录信息
        $managerInfo->setAttr('login_count', $managerInfo->getAttr('login_count') + 1);
        $managerInfo->setAttr('login_ip', Request::ip());
        $managerInfo->setAttr('login_time', date('Y-m-d H:i:s', Request::time()));
        $managerInfo->save();
        return $managerInfo->toArray();
    }

    /**
     * 分页列表
     * @param int $page 当前页
     * @param int $limit 显示数
     * @param null|int $roleId 角色 id
     * @param null|int $status 状态
     * @param string $keyword 模糊查询
     * @return array
     * @throws DbException
     */
    public function getList(int $page, int $limit, ?int $roleId, ?int $status, string $keyword): array
    {
        $whereArr = [];
        !is_null($roleId) ? $whereArr['role_id'] = $roleId : null;
        !is_null($status) ? $whereArr['status'] = $status : null;
        return $this->where(
            'account|bind_phone|nickname',
            'like',
            '%'.$keyword.'%'
        )
            ->where($whereArr)
            ->with(['role', 'image'])
            ->withAttr('bind_phone', function ($value, $data) {
                return encryptPhone($value, '****');
            })
            ->order(['login_time' => 'desc', 'id' => 'desc'])
            ->paginate([
            'list_rows' =>  $limit,
            'page'      =>  $page
        ])->toArray();
    }


    /**
     * 获取管理员信息
     * @param int $managerId
     * @return array|\think\Model
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function info(int $managerId) {
        $managerInfo = $this->with(['role', 'image'])->find($managerId);
        if (!$managerInfo) {
            throw new HttpException(404, '管理员信息不存在');
        }
        if ($managerInfo->getAttr('status') == 1) {
            throw new ValidateException('该帐户已被冻结，请联系管理员');
        }
        return $managerInfo;
    }

    /**
     * 批量 冻结/恢复
     * @param array $managerIds
     * @param int $status
     * @throws \Exception
     */
    public function changeStatus(array $managerIds, int $status): void {
        $updateData = [];
        foreach ($managerIds as $key => $managerId) {
            $updateData[$key]['id'] = $managerId;
            $updateData[$key]['status'] = $status;
        }
        $this->saveAll($updateData);
    }

    /**
     * 批量设置角色
     * @param array $managerIds
     * @param int $roleId
     * @throws \Exception
     */
    public function setRole(array $managerIds, int $roleId): void {
        $updateData = [];
        foreach ($managerIds as $key => $managerId) {
            $updateData[$key]['id'] = $managerId;
            $updateData[$key]['role_id'] = $roleId;
        }
        $this->saveAll($updateData);
    }

    /**
     * 管理员添加
     * @param array $postForm
     * @return bool
     */
    public function add(array $postForm): bool
    {
        $postForm['password'] = md5($postForm['password']);
        return $this->save($postForm);
    }

    /**
     * 管理员编辑
     * @param array $postForm
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function edit(array $postForm): bool
    {
        $managerInfo = $this->with(['role', 'image'])->find($postForm['id']);
        $roleInfo = $managerInfo->getAttr('role');
        if ($roleInfo['is_super'] == 1) {
            throw new ValidateException('超级管理员不可修改');
        }
        return $managerInfo->save($postForm);
    }

    /**
     * 获取当前用户的菜单
     * @param int $managerId
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function authMenu(int $managerId): array
    {
        // 获取当前用户角色信息
        $roleInfo = $this->info($managerId)->getAttr('role');
        $authIds = $roleInfo->getAttr('auth_ids');
        $isSuper = $roleInfo->getAttr('is_super');
        // 获取权限数据
        if ($isSuper == 1) {
            $authAll = (new Auth)->select();
        } else {
            $authAll = (new Auth)->where('status', 1)->whereIn('id', $authIds)->select();
        }
        // 递归组装无限极权限菜单
        return recurrenceLevel($authAll->toArray(), 0);
    }
}